home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / system / srouted-.000 / srouted- / srouted-0.1pl1 / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-20  |  7.5 KB  |  254 lines

  1. /* input.c -- input processing */
  2.  
  3. /*
  4.  *  srouted -- silent routing daemon
  5.  *  Copyright (C) 1995 Kevin Buhr
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Id: input.c,v 1.5 1995/02/20 17:45:38 buhr Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "defs.h"
  27. #include "table.h"
  28. #include "kernel.h"
  29. #include "output.h"
  30. #include "input.h"
  31.  
  32. #include <netinet/in.h>
  33.  
  34. static int in_czentry(struct rip *rip, int entry);
  35.  
  36.  
  37. /*
  38.  *    Count number of entries in a RIP packet
  39.  */
  40.  
  41. int in_countentries( int length )
  42. {
  43.    return ( length - sizeof( ((struct rip *)NULL)->rip_cmd )
  44.       - sizeof( ((struct rip *)NULL)->rip_vers )
  45.      - sizeof( ((struct rip *)NULL)->rip_res1 ) )
  46.       / sizeof( ((struct rip *)NULL)->rip_nets[0] );
  47. }
  48.  
  49.  
  50. /*
  51.  *    Check reserved areas in an entry
  52.  */
  53.  
  54. static int in_czentry(struct rip *rip, int entry)
  55. {
  56.    int i;
  57.  
  58.    for(i=0; i<14; i++) {
  59.       if(i==2) i=6;  /* skip IP address */
  60.       if(rip->rip_nets[entry].rip_dst.sa_data[i]) return(1);
  61.    }
  62.    return(0);
  63. }
  64.  
  65.  
  66. /*
  67.  *    Process a received RIP packet
  68.  */
  69.  
  70. void in_processrip(struct rip *rip, int length, struct sockaddr *safrom)
  71. {
  72.    int entry, entry_count;
  73.    struct netinfo *ni;
  74.    int ev=0;  /* if 1, then packet is of "expected" version */
  75.    struct tb_address from, dest;
  76.    short cost;
  77.    int route, netroute, samegw;
  78.  
  79.    from.tba_addr = *safrom;
  80.    tb_chkaddr(&from);
  81.  
  82.    note0( ERCIN_GOTINPUT );
  83.  
  84.    /* this must be from a valid, single-host address */
  85.    if( (from.tba_flags & TBAF_VALID)==0
  86.       || (from.tba_flags & TBAF_HOST)==0 ) {
  87.       warn0(ERCIN_BADFROM);
  88.       return;
  89.    }
  90.  
  91. #define CZI(thing) \
  92.    if(ev && (thing)!=0) { warn3(ERCIN_CZ,rip,length,&from); goto ignore_rip; }
  93. #define CZE(rip,entry) \
  94.    if(ev && in_czentry((rip),(entry))) { warn4(ERCIN_CZE,rip,length,&from,entry); continue; }
  95. #define CZEI(rip,entry) \
  96.    if(ev && in_czentry((rip),(entry))) { warn4(ERCIN_CZE,rip,length,&from,entry); goto ignore_rip; }
  97.    
  98.    if(rip->rip_vers==0) {
  99.       weakwarn3(ERCIN_VERS0,rip,length,&from);
  100.       goto ignore_rip;
  101.    }
  102.    ev=(rip->rip_vers==RIPVERSION);
  103.    CZI(rip->rip_res1[0]);
  104.    CZI(rip->rip_res1[1]);
  105.    if(rip->rip_cmd>RIPCMD_MAX) {
  106.       if(ev) {
  107.      warn3(ERCIN_UNKCMD,rip,length,&from);
  108.       } else {
  109.      weakwarn3(ERCIN_UNKCMD,rip,length,&from);
  110.       }
  111.       goto ignore_rip;
  112.    }
  113.  
  114.    switch(rip->rip_cmd) {
  115.    case 0:
  116.       warn3(ERCIN_CMD0,rip,length,&from);
  117.       goto ignore_rip;
  118.    case RIPCMD_TRACEON:
  119.    case RIPCMD_TRACEOFF:
  120.       weakwarn3(ERCIN_CMD34,rip,length,&from);
  121.       goto ignore_rip;
  122.    case 5:
  123.       weakwarn3(ERCIN_CMD5,rip,length,&from);
  124.       goto ignore_rip;
  125.  
  126.    case RIPCMD_REQUEST:
  127.       /* as silent process, we ignore rips from "normal" port */
  128.       if(from.tba_port == g_routedport) {
  129.      note3( ERCIN_IGNOREREQUEST, rip, length, &from );
  130.      goto ignore_rip;
  131.       }
  132.       note3( ERCIN_GOTREQUEST, rip, length, &from );
  133.       entry_count=in_countentries(length);
  134.       if(entry_count==1 &&
  135.      ntohs(rip->rip_nets[0].rip_dst.sa_family)==AF_UNSPEC &&
  136.      ntohl(rip->rip_nets[0].rip_metric)==TBM_INFINITY) {
  137.      CZEI(rip,0);
  138.      note0( ERCIN_REQWHOLE );
  139.      out_table(&from);   /* send whole table */
  140.       } else {
  141.      for(entry=0; entry<entry_count; entry++) {
  142.         CZE(rip,entry);
  143.         ni=&rip->rip_nets[entry];
  144.         if(ntohs(ni->rip_dst.sa_family) != AF_INET) {
  145.            weakwarn4(ERCIN_UNKAF,rip,length,&from,entry);
  146.            ni->rip_metric=htonl(TBM_INFINITY);
  147.            continue;
  148.         }
  149.         ni->rip_metric=htonl(tb_rtmetric(ni->rip_dst));
  150.         note5(ERCIN_REQENTRY,rip,length,&from,entry,ni->rip_metric);
  151.      }
  152.      note0( ERCIN_REQANSWER );
  153.      out_rip(rip,length,&from,RIPCMD_RESPONSE);
  154.       }
  155.       break;
  156.  
  157.    case RIPCMD_RESPONSE:
  158.       if(from.tba_port != g_routedport) {
  159.      warn3(ERCIN_RESPPORT,rip,length,&from);
  160.      goto ignore_rip;
  161.       }
  162.       /*** could check if allowed neighbour here! ***/
  163.       /* check that this came from someone directly connected */
  164.       if(from.tba_iface==-1) {
  165.      warn3(ERCIN_RESPREMOTE,rip,length,&from);
  166.      goto ignore_rip;
  167.       }
  168.    /**********************************************************
  169.     *   we can't be listening to ourselves, since we never   *
  170.     *   respond to port g_routedport                         *
  171.     **********************************************************/
  172.       note3( ERCIN_GOTRESPONSE, rip, length, &from );
  173.       entry_count=in_countentries(length);
  174.       for(entry=0; entry<entry_count; entry++) {
  175.      CZE(rip,entry);
  176.      ni=&rip->rip_nets[entry];
  177.      if(ntohl(ni->rip_metric) == 0 || 
  178.         ntohl(ni->rip_metric) > TBM_INFINITY) {
  179.         warn4(ERCIN_BADMETRIC,rip,length,&from,entry);
  180.         continue;
  181.      }
  182.      dest.tba_addr=ni->rip_dst;
  183.      dest.tba_addr.sa_family=ntohs(dest.tba_addr.sa_family);
  184.      tb_chkaddr(&dest);
  185.      if(dest.tba_af != AF_INET) {
  186.         weakwarn4(ERCIN_UNKAF,rip,length,&from,entry);
  187.         continue;
  188.      }
  189.      if( (dest.tba_flags & TBAF_VALID) == 0 ||
  190.         ( (dest.tba_flags & TBAF_DEFAULT) == 0 &&
  191.          ( (dest.tba_flags & TBAF_CLASSABC) == 0 ||
  192.           dest.tba_subnet == 0 || dest.tba_subnet == 0x7f000000 ||
  193.           (dest.tba_flags & TBAF_BROADCAST) ) ) ) {
  194.         weakwarn4(ERCIN_BADADDR,rip,length,&from,entry);
  195.         continue;
  196.      }
  197.      cost = ntohl(ni->rip_metric) + 
  198.         tb_iface[from.tba_iface].tbif_metric;
  199.      if( cost > TBM_INFINITY ) cost=TBM_INFINITY;
  200.      route = tb_findroute( &dest.tba_addr );
  201.      note6(ERCIN_RESENTRY, rip, length, &from, entry, cost, route);
  202.      if( route != -1 && tb_route[route].tbrt_flags & TBRTF_SUPERNET ) {
  203.         warn1( ERCIN_RTSUPER, &dest );
  204.         continue;
  205.      }
  206.      if( route == -1 ) {
  207.         if(cost == TBM_INFINITY )
  208.            continue;
  209.         /* ignore host route if we have a decent net route */
  210.         if( dest.tba_flags & TBAF_HOST ) {
  211.            netroute = tb_findroute( &dest.tba_subnetsa );
  212.            if( netroute != -1 && tb_route[netroute].tbrt_metric <= cost ) {
  213.           note1( ERCIN_IGNOREHOST, netroute );
  214.           continue;
  215.            }
  216.         }
  217.         route = tb_newroute();
  218.         if( route == -1 ) {
  219.            warn0(ERCIN_RTFULL);
  220.            continue;
  221.         }
  222.         tb_addroute( route, &dest, &from, cost );
  223.         note1( ERCIN_RESADDED, route );
  224.      } else {
  225.         note0( ERCIN_HADROUTE );
  226.         samegw = tb_samehost( &tb_route[route].tbrt_gateway,
  227.              &from.tba_addr );
  228.         if(samegw && cost == tb_route[route].tbrt_metric
  229.            && (tb_route[route].tbrt_flags & TBRTF_DELETED) == 0
  230.            && (tb_route[route].tbrt_flags & TBRTF_KILLED) == 0 ) {
  231.            note0( ERCIN_REPEATROUTE );
  232.            tm_settimeout( route );
  233.         }
  234.         if( (samegw && cost != tb_route[route].tbrt_metric)
  235.            || cost < tb_route[route].tbrt_metric
  236.            || (tb_route[route].tbrt_flags & TBRTF_TENTATIVE)
  237.            || (tb_route[route].tbrt_flags & TBRTF_KILLED) ) {
  238.            if( cost == TBM_INFINITY ) {
  239.           note1( ERCIN_RESDELETED, route );
  240.           tb_delroute( route, &from );
  241.            } else {
  242.           tb_addroute( route, &dest, &from, cost );
  243.           note1( ERCIN_RESADDED, route );
  244.            }
  245.         } else {
  246.            note0( ERCIN_RESIGNORED );
  247.         }
  248.      }
  249.       }
  250.    }
  251.  ignore_rip:
  252.    return;
  253. }
  254.